package com.jinwei.qunguanjia.user.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.jinwei.qunguanjia.common.constant.UserConstants;
import com.jinwei.qunguanjia.common.core.domain.model.Condition;
import com.jinwei.qunguanjia.common.core.page.PageDataInfo;
import com.jinwei.qunguanjia.common.core.redis.RedisCache;
import com.jinwei.qunguanjia.common.utils.*;
import com.jinwei.qunguanjia.user.dao.GroupDAO;
import com.jinwei.qunguanjia.user.dao.GroupLogoutDAO;
import com.jinwei.qunguanjia.user.dao.UserDAO;
import com.jinwei.qunguanjia.user.dao.UserLogoutDAO;
import com.jinwei.qunguanjia.user.dto.UserDTO;
import com.jinwei.qunguanjia.user.po.GroupLogoutPO;
import com.jinwei.qunguanjia.user.po.GroupPO;
import com.jinwei.qunguanjia.user.po.UserLogoutPO;
import com.jinwei.qunguanjia.user.po.UserPO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service("userService")
public class UserServiceImpl implements UserService {

    @Resource

    private UserDAO userDAO;

    @Resource
    private GroupDAO groupDAO;

    @Resource
    private UserLogoutDAO userLogoutDAO;

    @Resource
    private GroupLogoutDAO groupLogoutDAO;

    @Resource
    private RedisCache redisCache;

    @Resource
    private UserTokenService userTokenService;

    @Override
    public String save(UserDTO userDTO) {
        UserPO userPO = new UserPO();
        BeanUtils.copyProperties(userDTO, userPO);
        String userId = IdUtils.getWorkerId();
        userPO.setUserId(userId);
        userPO.setCreateTime(DateUtils.getDateTime());
        userDAO.insert(userPO);
        return userId;
    }

    @Override
    public void remove(String id) {
        userDAO.deleteById(id);
    }

    @Override
    public void update(UserDTO userDTO) {
        UserPO userPO = new UserPO();
        BeanUtils.copyProperties(userDTO, userPO);
        userPO.setUpdateTime(DateUtils.getDateTime());
        userDAO.updateById(userPO);
    }

    @Override
    public UserDTO get(String id) {
        UserPO userPO = userDAO.selectById(id);
        if (null == userPO) {
            return null;
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userPO, userDTO);
        return userDTO;
    }

    @Override
    public UserDTO get(UserDTO userDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(userDTO);
        // 拼接查询条件
        QueryWrapper<UserPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        UserPO userPO = userDAO.selectOne(queryWrapper);
        if (null == userPO) {
            return null;
        }
        BeanUtils.copyProperties(userPO, userDTO);
        return userDTO;
    }

    @Override
    public Long count(UserDTO userDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(userDTO);
        // 拼接查询条件
        QueryWrapper<UserPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        return userDAO.selectCount(queryWrapper);
    }

    @Override
    public List<UserDTO> list(UserDTO userDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(userDTO);
        // 拼接查询条件
        QueryWrapper<UserPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        return JsonUtils.copyList(userDAO.selectList(queryWrapper), UserDTO.class);
    }

    @Override
    public List<UserDTO> listAll() {
        // 实现获取所有用户的逻辑
        List<UserPO> userPOList = userDAO.selectList(null);
        return JsonUtils.copyList(userPOList, UserDTO.class);
    }

    @Override
    public PageDataInfo<UserDTO> listPage(UserDTO userDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(userDTO);
        // 拼接查询条件
        QueryWrapper<UserPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        List<UserPO> list = userDAO.selectList(queryWrapper);
        PageInfo<UserPO> pageInfo = new PageInfo<>(list);
        PageDataInfo<UserDTO> pageDataInfo = new PageDataInfo<>();
        pageDataInfo.setData(JsonUtils.copyList(list, UserDTO.class));
        pageDataInfo.setTotal(pageInfo.getTotal());
        pageDataInfo.setTotalPage(PageCountUtils.getPageCount(pageInfo.getTotal(), pageInfo.getPageSize()));
        return pageDataInfo;
    }

    @Override
    public String checkUnique(UserDTO userDTO) throws IllegalAccessException {
        String userId = StringUtils.isNull(userDTO.getUserId()) ? "-1" : userDTO.getUserId();
        UserDTO info = get(userDTO);
        if (StringUtils.isNotNull(info) && !info.getUserId().equals(userId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    @Transactional
    public void logout(String userId) {
        LambdaQueryWrapper<UserPO> userLambdaWrapper = new LambdaQueryWrapper<>();
        userLambdaWrapper.in(UserPO::getUserId, userId);
        UserPO userPO = userDAO.selectOne(userLambdaWrapper);
        UserLogoutPO userLogoutPO = new UserLogoutPO();
        BeanUtils.copyProperties(userPO, userLogoutPO);
        userLogoutDAO.insert(userLogoutPO);
        LambdaQueryWrapper<GroupPO> groupLambdaWrapper = new LambdaQueryWrapper<>();
        groupLambdaWrapper.in(GroupPO::getUserId, userId);
        List<GroupPO> groupList = groupDAO.selectList(groupLambdaWrapper);
        for (GroupPO groupPO : groupList) {
            GroupLogoutPO groupLogoutPO = new GroupLogoutPO();
            BeanUtils.copyProperties(groupPO, groupLogoutPO);
            groupLogoutDAO.insert(groupLogoutPO);
        }
        String token = redisCache.getCacheObject(userTokenService.getUserNameKey(userPO.getPhoneNumber()));
        if(null != token){
            redisCache.deleteObject(userTokenService.getUserNameKey(userPO.getPhoneNumber()));
            redisCache.deleteObject(userTokenService.getTokenKey(token));
        }
        userDAO.deleteById(userId);
        LambdaQueryWrapper<GroupPO> userLogoutLambdaWrapper = new LambdaQueryWrapper<>();
        userLogoutLambdaWrapper.in(GroupPO::getUserId, userId);
        groupDAO.delete(userLogoutLambdaWrapper);
    }
}
